package org.study.util;

import com.alibaba.fastjson2.JSON;

import java.util.*;

/**
 * 自定义数组工具类。https://www.cnblogs.com/passedbylove/p/12462613.html
 *
 * @author Administrator
 * @date 2021-11-23
 */
public class ArrayUtils {
    public static void main(String[] args) {
        Integer[] intArray = new Integer[10];
        for (int i = 0; i < 10; i++) {
            intArray[i] = i;
        }
        List<Integer[]> segment = splitBySegment(intArray, 3);
        System.out.println("按段数分割：" + JSON.toJSONString(segment));
        List<Integer[]> count = splitByCount(intArray, 3);
        System.out.println("按大小分割：" + JSON.toJSONString(count));
    }

    /**
     * 分割数组：按段数分割。注意：多出部分数据在最后一个数组中
     *
     * @param data     被分割的数据
     * @param segments 需要分割的段数
     * @return
     */
    public static <T> List<T[]> splitBySegment(T[] data, int segments) {
        List<T[]> result = new ArrayList<>();
        // 数据长度
        int size = data.length;
        if (size > 0 && segments > 0) {
            // 每段数量
            int count = size / segments;
            for (int i = 0; i < segments; i++) {
                // 每段中的数组元素
                T[] range = null;
                if (i == segments - 1) {
                    range = Arrays.copyOfRange(data, count * i, data.length);
                } else {
                    range = Arrays.copyOfRange(data, count * i, count * (i + 1));
                }
                result.add(range);
            }
        } else {
            // segments == 0 不需要分隔
            result.add(data);
        }
        return result;
    }

    /**
     * 分割数组：按大小分割
     *
     * @param data    被分割的数据
     * @param subSize 分割后每段大小
     * @return
     */
    public static <T> List<T[]> splitByCount(T[] data, int subSize) {
        List<T[]> result = new ArrayList<>();
        // 当前开始位置
        int curPos = 0;
        while (curPos < data.length) {
            // 剩余元素个数
            int remaining = data.length - curPos + 1;
            // 每段中的数组元素
            T[] range = null;
            if (remaining <= subSize) {
                range = Arrays.copyOfRange(data, curPos, data.length);
            } else {
                range = Arrays.copyOfRange(data, curPos, curPos + subSize);
            }
            result.add(range);
            curPos += subSize;
        }
        return result;
    }

    /**
     * 将 byte 数组按照指定大小分割成多个数组
     *
     * @param data    要分割的byte数组
     * @param subSize 分割后每段大小，单位：字节
     * @return 指定大小的 byte 数组
     */
    public static List<byte[]> splitByteArray(byte[] data, int subSize) {
        List<byte[]> result = new ArrayList<>();
        // 分割后会有多少段
        int count = data.length % subSize == 0 ? data.length / subSize : data.length / subSize + 1;
        List<List<Byte>> subArrayList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            int index = i * subSize;
            List<Byte> list = new ArrayList<>();
            int j = 0;
            while (j < subSize && index < data.length) {
                list.add(data[index++]);
                j++;
            }
            subArrayList.add(list);
        }
        for (int i = 0; i < subArrayList.size(); i++) {
            List<Byte> subList = subArrayList.get(i);
            byte[] subArray = new byte[subList.size()];
            for (int j = 0; j < subList.size(); j++) {
                subArray[j] = subList.get(j);
            }
            result.add(subArray);
        }
        return result;
    }

    /**
     * byte[] 转十六进制字符串
     *
     * @param src
     * @return java.lang.String
     */
    public static String bytesToHexString(byte[] src) {
        if (src == null || src.length <= 0) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder("");
        try {
            for (int i = 0; i < src.length; i++) {
                int v = src[i] & 0xFF;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }
                stringBuilder.append(hv);
            }
            return stringBuilder.toString();
        } catch (StackOverflowError e) {
            return null;
        }
    }
}
